// 示例数据：有向图的节点和边


function init() {
  // 获取按钮元素
  const showNodesButton = document.getElementById('showNodesButton');
  // 为按钮添加点击事件监听器
  showNodesButton.addEventListener('click', async () => {
    await shwoSearchNode();
  });

  document.getElementById('root-location').value = "/manage/general_controller/parseScript/";
  document.getElementById('script-search-path').value = "take(semanticNet,),node";

  document.getElementById('visitor-model').value
    = "/manage/general_controller/concept/interfaceModel/";

  document.getElementById('visited-model').value
    = "/manage/general_controller/concept/testModel/";

  document.getElementById('evaluation-script').value = "城市";
  document.getElementById('target-concept').value = "copy";

  document.getElementById('semantic-network').value = "testModel";
  document.getElementById('formula-script').value = "省份=省份1\n城市=城市1";
  document.getElementById('current-location').value = "(省份1,山西)";


  //  document.getElementById('visit-concept-name').value = "case1";
  //  document.getElementById('visit-define-script').value = "relation 包含(A,B)\nA->B=[0,)\nobject 省份 城市\n" +
  //    "包含(省份,城市)\nbuildMap((省份,城市),((浙江,杭州),(浙江,金华)))";

  fetch('/manage/file/introduce')
    .then(response => response.text())
    .then(markdownText => {
      // 将 Markdown 转换为 HTML
      const htmlContent = marked.parse(markdownText);
      // 将渲染后的 HTML 插入到页面中
      document.getElementById('markdown-content').innerHTML = htmlContent;
    })
    .catch(error => console.error('Error loading Markdown file:', error));

  fetch('/manage/file/todo')
    .then(response => response.text())
    .then(markdownText => {
      // 将 Markdown 转换为 HTML
      const htmlContent = marked.parse(markdownText);
      // 将渲染后的 HTML 插入到页面中
      document.getElementById('markdown-myGoal').innerHTML = htmlContent;
    })
    .catch(error => console.error('Error loading Markdown file:', error));

  fetch('/manage/file/targetProduct')
    .then(response => response.text())
    .then(markdownText => {
      // 将 Markdown 转换为 HTML
      const htmlContent = marked.parse(markdownText);
      // 将渲染后的 HTML 插入到页面中
      document.getElementById('markdown-targetProduct').innerHTML = htmlContent;
    })
    .catch(error => console.error('Error loading Markdown file:', error));

  fetch('/manage/file/businessPlan')
    .then(response => response.text())
    .then(markdownText => {
      // 将 Markdown 转换为 HTML
      const htmlContent = marked.parse(markdownText);
      // 将渲染后的 HTML 插入到页面中
      document.getElementById('markdown-businessPlan').innerHTML = htmlContent;
    })
    .catch(error => console.error('Error loading Markdown file:', error));

}

init();

function showPage(pageId) {
  // 隐藏所有页面
  const pages = document.querySelectorAll('.page');
  pages.forEach(page => {
    page.classList.remove('active');
  });

  // 显示选中的页面
  const selectedPage = document.getElementById(pageId);
  selectedPage.classList.add('active');
}

// 创建 CodeMirror 实例
const editor = CodeMirror.fromTextArea(document.getElementById('editor'), {
  mode: 'javascript', // 设置语言模式为 JavaScript
  lineNumbers: true // 显示行号
});

const defaultCode = `
 relation 属性(A,B)
     A->B=1 //代表 针对任意一个A，都可以找到 1个B与之对应

 object 人 身高 体重 数字

 属性(人,身高)
 属性(人,体重)
 属性(身高,数字)
 属性(体重,数字)

 `;
editor.setValue(defaultCode);

const confirmButton = document.getElementById('confirmButton');

confirmButton.addEventListener('click', async function () {
  const code = editor.getValue();
  console.log('用户输入的代码：', code);
  // 这里可以添加更多的处理逻辑，比如将代码发送到服务器等

  let nodeList = []

  nodeList.push({
    objectName: "语义网络脚本",
    value: code
  });

  const container = "#script-show";

  const dest = "语义网络结构";

  let result = await taskPath(nodeList, dest);

  console.log('Graph data:', result); // 打印生成的图数据


  const containerElement = document.querySelector(container);
  // 计算剩余屏幕宽度
  const remainingWidth = window.innerWidth - containerElement.offsetLeft;

  const graphData = {
    nodes: result[0].nodes.map(node => ({
      id: node.id,
      name: node.name
    })),
    links: result[0].links.map(link => ({
      source: link.from,
      target: link.to
    }))
  };

  const resultContainer = d3.select("#script-show");
  resultContainer.html("")
  await showdata(container, "800", graphData);

});




async function showdata(container, width, data, rawData) {
  // 初始化 D3.js 力导向图
  //const width = window.innerWidth;
  const height = 300;

  const svg = d3
    .select(container)
    .append("svg")
    .attr("width", width)
    .attr("height", height);

  svg.append("defs").append("marker")
    .attr("id", "arrowhead")
    .attr("viewBox", "0 -5 10 10")
    .attr("refX", 13)
    .attr("refY", 0)
    .attr("markerWidth", 6)
    .attr("markerHeight", 6)
    .attr("orient", "auto")
    .append("path")
    .attr("d", "M0,-5L10,0L0,5");


  const simulation = d3
    .forceSimulation(data.nodes)
    .force("link", d3.forceLink(data.links).id((d) => d.id))
    .force("charge", d3.forceManyBody().strength(-400))
    .force("center", d3.forceCenter(width / 2, height / 2));


  // 绘制边
  const links = svg
    .selectAll("line")
    .data(data.links)
    .enter()
    .append("line")
    .attr("stroke", "#999")
    .attr("stroke-width", 2)
    .attr("marker-end", "url(#arrowhead)"); // 应用箭头标记

  // 绘制节点
  const nodes = svg
    .selectAll("circle")
    .data(data.nodes)
    .enter()
    .append("circle")
    .attr("r", 10)
    .attr("fill", "#69b3a2")
    .call(
      d3
        .drag()
        .on("start", (event) => {
          if (!event.active) simulation.alphaTarget(0.3).restart();
          event.subject.fx = event.subject.x;
          event.subject.fy = event.subject.y;
        })
        .on("drag", (event) => {
          event.subject.fx = event.x;
          event.subject.fy = event.y;
        })
        .on("end", (event) => {
          if (!event.active) simulation.alphaTarget(0);
          event.subject.fx = null;
          event.subject.fy = null;
        })
    );

  // 添加节点标签
  const labels = svg
    .selectAll("text")
    .data(data.nodes)
    .enter()
    .append("text")
    .text((d) => d.name)
    .attr("font-size", 12)
    .attr("dx", 15)
    .attr("dy", 4);

  // 更新图形位置
  simulation.on("tick", () => {
    links
      .attr("x1", (d) => d.source.x)
      .attr("y1", (d) => d.source.y)
      .attr("x2", (d) => d.target.x)
      .attr("y2", (d) => d.target.y);

    nodes.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
    labels.attr("x", (d) => d.x).attr("y", (d) => d.y);
  });

  // 创建缩放行为
  const zoom = d3.zoom()
    .scaleExtent([0.5, 5]) // 设置缩放范围
    .on("zoom", (event) => {
      // 处理缩放事件
      svg.selectAll("line, circle,text")
        .attr("transform", event.transform);
    });

  // 应用缩放行为到 SVG
  svg.call(zoom);

  if (container != "#graph-container" && container != "#script-show") {

    const buttonX = 160; // 按钮宽度假设为 80px，使其居中
    const buttonY = height - 50; // 按钮在图片下方 10px

    const button = svg.append("foreignObject")
      .attr("x", buttonX)
      .attr("y", buttonY)
      .attr("width", 80)
      .attr("height", 30)
      .append("xhtml:button")
      .text("执行路径");

    button.datum(rawData);

    button.on("click", function (event, d) {
      // 读取绑定的数据
      const data = d;

      const modal = d3.select("#myModal");
      const inputContainer = d3.select("#input-container");
      const resultContainer = d3.select("#result-container");
      const confirmBtn = d3.select("#confirm-btn");
      const cancelBtn = d3.select("#cancel-btn");
      const closeBtn = d3.select(".close");

      cancelBtn.on("click", function () {
        modal.style("display", "none");
      });
      closeBtn.on("click", function () {
        modal.style("display", "none");
      });


      inputContainer.html("");

      // 根据字符串数组生成描述和输入框
      data.requestParam.forEach((node) => {
        const inputGroup = inputContainer.append("div").attr("class", "input-group");
        inputGroup.append("label").text(node.name + ": ");
        inputGroup.append("input")
          .attr("type", "text")
          .attr("id", node.id);
      });


      // 为确认按钮添加点击事件监听器
      confirmBtn.on("click", async function () {
        const inputs = inputContainer.selectAll("input");
        const inputValues = {};
        inputs.each(function () {
          inputValues[d3.select(this).property("id")] = d3.select(this).property("value")
        });
        console.log("输入的值:", inputValues);

        let nodeList = []
        let dest = data.destObj.id;

        let allRequestKeyLs = []

        data.allRequestParam.forEach((node) => {
          allRequestKeyLs.push(node.id);
        });

        allRequestKeyLs.forEach((key) => {
          nodeList.push({
            objectName: key,
            value: inputValues[key]
          });

        });
        let result = await taskPath(nodeList, dest);
        const jsonString = JSON.stringify(result);
        resultContainer.html("");
        resultContainer.append("label").text(jsonString);
      });

      modal.style("display", "block");

    });

  }

  // // 搜索功能
  // const searchBox = document.getElementById("search-box");
  // searchBox.addEventListener("input", (event) => {
  //   const searchTerm = event.target.value.toLowerCase();
  //   nodes.attr("fill", (d) =>
  //     d.name.toLowerCase().includes(searchTerm) ? "#69b3a2" : "#ccc"
  //   );
  // });
}

async function showAllNode() {

  const allLinks = await getAllLink(); // 等待 getAllLink 完成
  const allNodes = await getAllNode(); // 等待 getAllNode 完成

  const graphData = {
    nodes: allNodes.map(node => ({
      id: node.id,
      name: node.name
    })),
    links: allLinks.map(link => ({
      source: link.from,
      target: link.to
    }))
  };
  console.log('Graph data:', graphData); // 打印生成的图数据

  const container = "#graph-container"

  const containerElement = document.querySelector(container);
  // 计算剩余屏幕宽度
  const remainingWidth = window.innerWidth - containerElement.offsetLeft;
  //- containerElement.offsetWidth;
  await showdata(container, "1000", graphData);
}




async function shwoSearchNode() {

  const searchStart = document.getElementById("search-start").value;
  const searchDest = document.getElementById("search-dest").value;

  if (searchStart == "") {
    alert("来源节点不能为空")
    return
  }
  if (searchDest == "") {
    alert("目标节点不能为空")
    return
  }

  start = searchStart.split(";");
  let allPossiblePath = await searchPath(start, searchDest);

  let container = "#graph-pathShow"

  d3.select(container).selectAll("*").remove();

  for (let i = 0; i < allPossiblePath.length; i++) {

    const graphData = {
      nodes: allPossiblePath[i].nodes.map(node => ({
        id: node.id,
        name: node.name
      })),
      links: allPossiblePath[i].links.map(link => ({
        source: link.from,
        target: link.to
      }))
    };

    await showdata(container, 400, graphData, allPossiblePath[i]);

  }

}

showAllNode();




/*---------------------------------------------------client---------------------------------------------------------*/


async function getAllLink() {
  try {
    const response = await fetch('/manage/general_controller/getAllLink'); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
  }
}



async function getAllNode() {
  try {
    const response = await fetch('/manage/general_controller/getAllNode'); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
  }
}


async function takePath(path, dest) {
  try {
    const response = await fetch(path + ',' + dest); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    if (!data.success) {
      throw new Error(data.errorMessage);
    }
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
    throw error;
  }
}

async function execScript(path, dest) {
  try {
    const response = await fetch(path + dest); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    if (!data.success) {
      throw new Error(data.errorMessage);
    }
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
    throw error;
  }
}

async function searchPath(source, dest) {
  try {
    const response = await fetch('/manage/general_controller/searchPath',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          from: source,
          destObject: dest
        })
      }
    ); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
  }
}


async function taskPath(source, dest) {
  try {
    const response = await fetch('/manage/general_controller/getValue',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          from: source,
          destObject: dest
        })
      }
    ); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
  }
}


async function confirmAction() {
  const location = document.getElementById('location').value;
  const searchPath = document.getElementById('search-path').value;
  const displayBox = document.getElementById('display-box');

  if (location && searchPath) {
    const result = await takePath(location, searchPath)
    displayBox.textContent = result;
  } else {
    displayBox.textContent = '请填写所有字段';
  }
}

async function scriptConfirmAction() {
  const location = document.getElementById('root-location').value;
  const searchPath = document.getElementById('script-search-path').value;
  const displayBox = document.getElementById('script-box');

  if (location && searchPath) {
    const result = await execScript(location, searchPath)
    displayBox.textContent = result;
  } else {
    displayBox.textContent = '请填写所有字段';
  }
}



async function showInterfaceModel() {
  await showStruct("/manage/general_controller/concept/interfaceModel/", "#visitor-interface-show");
}


async function showImplementModel() {
  await showStruct("/manage/general_controller/concept/testModel/", "#visited-implement-show");
}

async function showModel() {
  const url = document.getElementById('root-location').value;
  await showStruct(url, "#map-show");
}

async function showStruct(interfaceUrl, container) {

  let node = await takePath(interfaceUrl + "take(semanticNet,)", "node");
  let link = await takePath(interfaceUrl + "take(semanticNet,)", "link");
  node = JSON.parse(node)
  link = JSON.parse(link)
  const graphData = {
    nodes: node.map(node => ({
      id: node.id,
      name: node.name
    })),
    links: link.map(link => ({
      source: link.from,
      target: link.to
    }))
  };
  const resultContainer = d3.select(container);
  resultContainer.html("")
  await showdata(container, "800", graphData);
}


async function realDemoShow() {
  const evaluationScript = document.getElementById('evaluation-script').value;
  const url = document.getElementById('destCallUrl-box').textContent;
  const displayBox = document.getElementById('value-box');
  if (url && evaluationScript) {
    const result = await execScript(url + ",", evaluationScript)
    displayBox.textContent = result;
  } else {
    displayBox.textContent = '目标调用url为空';
  }
}

let testCase = {

  "diffNameCase": {
    sourceConcept: "diffNameCase-visitor",
    buildScript: "relation 包含(A,B)\nA->B=[0,)\nobject 省份 城市\n" +
      "包含(省份,城市)",
    visitObject: "省份",
    evalScript: "城市",

    destConcept: "diffNameCase-visited",
    destBuildScript: "relation 包含(A,B)\nA->B=[0,)\nobject 省份a 城市a\n" +
      "包含(省份a,城市a)\nbuildMap((省份a,城市a),((浙江,杭州),(浙江,金华)))",
    mergeScript: "eq 城市=城市a\neq 省份=省份a",
    visitObjValue: "(省份a,浙江)",
  },
  "diffStructCase": {
    sourceConcept: "diffStructCase-visitor",
    buildScript: "relation 包含(A,B)\nA->B=[0,)\nobject 国家 城市\n" +
      "包含(国家,城市)",
    visitObject: "国家",
    evalScript: "城市",

    destConcept: "diffStructCase-visited",
    destBuildScript: "relation 包含(A,B)\nA->B=[0,)\nobject 国家a 省份a 城市a\n" +
      "包含(国家a,省份a)\n包含(省份a,城市a)\nbuildMap((省份a,城市a),((浙江,杭州),(浙江,绍兴)))"
      + "\nbuildMap((国家a,省份a),((中国,浙江)))",
    mergeScript: "eq 城市=城市a\neq 国家=国家a",
    visitObjValue: "(国家a,中国)",
  },
  "diffDimCase": {
    sourceConcept: "diffDimCase-visitor",
    buildScript: "relation 找到(A,B)\nA->B=1\nobject 中国手机号 人\n" +
      "找到(中国手机号,人)",
    visitObject: "中国手机号",
    evalScript: "人",

    destConcept: "diffDimCase-visited",
    destBuildScript: "relation 找到(A,B)\nA->B=[0,)\nrelation 二元找到(A,B,C)\n(A,B)->C=1\n"
      + "object  区号 手机号 联系人\n"
      + "二元找到(区号,手机号,联系人)\n"
      + "buildMap((手机号,区号,联系人),((13412341234,86,张三)))\n",
    mergeScript:    "relation 找到(A,B)\n"
                 + "A->B=1\n"
                 + "找到(中国手机号,手机号)\n"
                 + "找到(中国手机号,区号)\n"
                 + "找到(联系人,人)\n"
                 + "buildMap((中国手机号,区号),((13412341234,86)))\n"
                 + "buildMap((中国手机号,手机号),((13412341234,13412341234)))\n"
                 + "buildMap((联系人,人),((张三,张三)))\n",
    visitObjValue: "(中国手机号,13412341234)",
  }

}

async function setCaseData(testCaseKey) {

  const data = testCase[testCaseKey];
  document.getElementById('visit-concept-name').value = data.sourceConcept;
  document.getElementById('visit-define-script').value = data.buildScript;
  document.getElementById('visit-object').value = data.visitObject;
  document.getElementById('eval-script').value = data.evalScript;

  document.getElementById('visited-concept-name').value = data.destConcept;
  document.getElementById('visited-define-script').value = data.destBuildScript;
  document.getElementById('to-same-level-script').value = data.mergeScript;
  document.getElementById('location').value = data.visitObjValue;

}


async function submit_script() {
  const conceptName = document.getElementById('visit-concept-name').value;
  const script = document.getElementById('visit-define-script').value;
  const res = await post_script(conceptName, script);
  if (res && !res) {
    showNotification(res)
  } else {
    showNotification("成功");
  }
}

async function submit_visited_script() {
  const conceptName = document.getElementById('visited-concept-name').value;
  const script = document.getElementById('visited-define-script').value;
  const res = await post_script(conceptName, script);
  if (res) {
    showNotification(res)
  } else {
    showNotification("成功");
  }
}

const baseUrl = "/manage/general_controller/concept/";



async function submit_visitedAndBuildMerge() {
  const sourceConceptName = document.getElementById('visit-concept-name').value;
  const conceptName = document.getElementById('visited-concept-name').value;
  const script = document.getElementById('visited-define-script').value;
  const res = await post_script(conceptName, script);
  if (res && !res) {
    showNotification(res);
  }
  const mergeScript = document.getElementById('to-same-level-script').value;
  const location = document.getElementById('location').value;
  try {
    const displayBox = document.getElementById('locationUrl');
    const url = await createInterfaceModel(baseUrl + sourceConceptName + "/", null, conceptName, mergeScript, location, sourceConceptName + "copy")
    displayBox.value = url.url;
  } catch (error) {
    showNotification(error);
  }
}


async function allCaseDemoShow() {
  const evaluationScript = document.getElementById('eval-script').value;
  const url = document.getElementById('locationUrl').value;
  const displayBox = document.getElementById('return-value');
  if (url && evaluationScript) {
  try {
        const result = await execScript(url + ",", evaluationScript)
        displayBox.value = result;
    } catch (error) {
      showNotification(error);
    }
  } else {
    showNotification('目标调用url为空');
  }
}


async function post_script(conceptName, script) {
  try {
    const response = await fetch('/manage/general_controller/parse',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          conceptName: conceptName,
          script: script
        })
      }
    ); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    if (!data.success) {
      throw new Error(data.errorMessage);
    }
    return data.result;
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
    throw error;
  }
}


async function genCallUrl() {
  const visitor = document.getElementById('visitor-model').value;
  const evaluationScript = document.getElementById('evaluation-script').value;

  const targetConcept = document.getElementById('target-concept').value;
  const formula = document.getElementById('formula-script').value;

  const network = document.getElementById('semantic-network').value;// 实现语义网络
  const current = document.getElementById('current-location').value;

  const displayBox = document.getElementById('destCallUrl-box');

  if (visitor && script && network && formula && current) {
    const url = await createInterfaceModel(visitor, evaluationScript, network, formula, current, targetConcept)
    displayBox.textContent = url.url;
  } else {
    displayBox.textContent = '请填写所有字段';
  }
}

async function createInterfaceModel(visitor, evaluationScript, implement, formula, current, targetConcept) {
  try {
    const response = await fetch('/manage/general_controller/createInterfaceModel',
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          targetInterfaceUrl: visitor,
          targetConceptName: targetConcept,
          implementConcept: implement,
          script: formula,
          currentPosition: current
        })
      }
    ); // 替换为你的后端接口
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();
    if (!data.success) {
      throw new Error(data.errorMessage);
    }
    return data.result;
  } catch (error) {
    console.error('Error fetching graph data:', error);
    throw error;
  }
}

function showNotification(message, duration = 1500) {
  // 创建提示元素
  const notification = document.createElement('div');
  notification.textContent = message;

  // 基础样式
  notification.style.position = 'fixed';
  notification.style.top = '20px';
  notification.style.left = '50%';
  notification.style.transform = 'translateX(-50%)';
  notification.style.backgroundColor = 'rgba(0,0,150,0.8)';
  notification.style.color = 'white';
  notification.style.padding = '12px 24px';
  notification.style.borderRadius = '4px';
  notification.style.zIndex = '10000'; // 确保在最顶层
  notification.style.transition = 'opacity 0.3s';

  // 添加到页面
  document.body.appendChild(notification);

  // 短暂延迟后触发渐隐动画
  setTimeout(() => {
    notification.style.opacity = '0';
  }, duration - 300); // 提前开始渐隐

  // 动画结束后移除元素
  setTimeout(() => {
    document.body.removeChild(notification);
  }, duration);
}